﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//int main()
//{
//	//char ch = 'w';
//	//char*p=&ch;
//	//*p = 'b';
//
//	//const char* str = 'abcdef';
//
//	//指针数组
//	//int* arr[10];
//	//char* arr2[4];
//	//
//
//	//数组指针
//
//	int(*arr)[5];
//
//	return 0;
//}


////数组参数
//
//#include <stdio.h>
//void test(int arr[])//ok?
//{}
//void test(int arr[10])//ok?
//{}
//void test(int *arr)//ok?
//{}
//void test2(int *arr[20])//ok?
//{}
//void test2(int **arr)//ok?
//{}
//int main()
//{
//	int arr[10] = { 0 };
//	int *arr2[20] = { 0 };
//	test(arr);
//	test2(arr2);
//}


//void test(int arr[3][5])//ok？
//{}
//// void test(int arr[][])//ok？ err
////{}
//void test(int arr[][5])//ok？
//{}
////总结：二维数组传参，函数形参的设计只能省略第一个[]的数字。
////因为对一个二维数组，可以不知道有多少行，但是必须知道一行多少元素。
////这样才方便运算。
//void test(int *arr)//ok？ err,传过来的二维数组的第一行的地址，整型指针用来存放整型变量的地址
//{}
//void test(int* arr[5])//ok？err，指针数组
//{}
//void test(int(*arr)[5])//ok？
//{}
//void test(int **arr)//ok？err,
//{}
//int main()
//{
//	int arr[3][5] = { 0 };
//	test(arr);//二维数组的首元素实质指的是第一行.
//}

//指针传参
//一级指针传参，当一个函数的参数部分为一级指针的时候，函数能接收什么参数？
#include <stdio.h>
//void print(int *p, int sz) {
//	int i = 0;
//	for (i = 0; i<sz; i++)
//	{
//		printf("%d\n", *(p + i));
//	}
//}
//
//void print(int p[], int sz) {
//	int i = 0;
//	for (i = 0; i<sz; i++)
//	{
//		printf("%d\n", *(p + i));
//	}
//}
//int main()
//{
//	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 ,10};
//	int *p = arr;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	//一级指针p，传给函数
//	print(p, sz);
//	return 0;
//}


//void test(int *p)
//{
//}
//
//int main()
//{
//	int a = 10;
//	int*p1 = &a;
//	int arr[10] = { 0 };
//
//	test(&a);
//	test(arr);
//	test(p1);
//	test(NULL);
//	return 0;
//}



//#include <stdio.h>
//void test(int** ptr) {
//	printf("num = %d\n", **ptr);
//}
//int main()
//{
//	int n = 10;
//	int*p = &n;
//	int **pp = &p;
//	int* arr[5];
//
//	test(pp);
//	test(&p);
//	test(arr);//指针数组的数组名可以传过去
//
//	return 0;
//}

//整型指针
//字符指针
//数组指针
//函数指针变量-存放函数的地址
//
//#include <stdio.h>
//void test()
//{
//	printf("hehe\n");
//}
//int main()
//{
//	printf("%p\n", test);
//	printf("%p\n", &test);
//	return 0;
//}

//函数声明
//函数定义
//函数调用
//typedef void(*pfun_t)(int);
////pfun_t signal(int, pfun_t);
//
//int main()
//{
//	//代码1 
//	(*(void (*)())0)();
//	//0本来是整型，然后对0进行强制类型转化成void(*)(),被当成一个函数地址，
//	//*解引用，找到那个函数，调用那个函数
//	//解释；代码是一次函数调用
//	//1.代码中把0强制类型转换为void(*)()的一个函数地址
//	//2.(*(void (*)())0)，解引用0地址，就是去调用0地址处的这个函数，被调用的函数是无参，返回类型是void
//
//
//	//代码2
//	//这个代码是一次函数声明
//	//声明的函数名是signal
//	//signal函数有两个参数，第一个是int类型，第二个是void(*)(int)的函数指针类型
//	//signal函数的返回类型是void(*)(int)的函数指针类型
//	//
//	void(*signal(int, void(*)(int)))(int);
//
//	pfun_t signal2(int, pfun_t);
//
//	//void(*)(int)signal(int, void(*)(int));//err
//
//
//
//	return 0;
//}


//#include <stdio.h>
//int add(int a, int b) {
//	return a + b;
//}
//int sub(int a, int b) {
//	return a - b;
//}
//int mul(int a, int b) {
//	return a*b;
//}
//int div(int a, int b) {
//	return a / b;
//}
//int main()
//{
//	int x, y;
//	int input = 1;
//	int ret = 0;
//	do
//	{
//		printf("*************************\n");
//		printf(" 1:add           2:sub \n");
//		printf(" 3:mul           4:div \n");
//		printf("*************************\n");
//		printf("请选择：");
//		scanf("%d", &input);
//		switch (input)
//		{
//		case 1: 
//			printf("输入操作数：");
//			scanf("%d %d", &x, &y);
//			ret = add(x, y);
//			printf("ret = %d\n", ret);
//			break;
//		case 2:
//			printf("输入操作数：");
//			scanf("%d %d", &x, &y);
//			ret = sub(x, y);
//			printf("ret = %d\n", ret);
//			break;
//		case 3:
//			printf("输入操作数：");
//			scanf("%d %d", &x, &y);
//			ret = mul(x, y);
//			printf("ret = %d\n", ret);
//			break;
//		case 4:
//			printf("输入操作数：");
//			scanf("%d %d", &x, &y);
//			ret = div(x, y);
//			printf("ret = %d\n", ret);
//			break;
//		case 0:
//			printf("退出程序\n");
//			break;
//		default:
//			printf("选择错误\n");
//			break;
//		}
//	} while (input);
//
//	return 0;
//}

//函数改进版
#include <stdio.h>
int add(int a, int b) {
	return a + b;
}
int sub(int a, int b) {
	return a - b;
}
int mul(int a, int b) {
	return a*b;
}
int div(int a, int b) {
	return a / b;
}
int main()
{
	int x, y; int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
	while (input)
	{
		printf("*************************\n");
		printf(" 1:add           2:sub \n");
		printf(" 3:mul           4:div \n");
		printf("*************************\n");
		printf("请选择：");
		scanf("%d", &input);
		if ((input <= 4 && input >= 1))
		{
			printf("输入操作数：");
			scanf("%d %d", &x, &y);
			ret = (*p[input])(x, y);
		}
		else
			printf("输入有误\n");
		printf("ret = %d\n", ret);
	}
	return 0;
}